Skip to content

Commit 60ee644

Browse files
authored
feat(pyndakaas): add reflected operators for BoolExp, Formula, and Lit (#100)
* Allow creating BoolLinExps from list of vars/lits * Fix the issue using `__radd__` * Remove unnecessary constructor * Add remaining reciprocal functions * Add missing BoolLinExp operations
1 parent 8aa6f5d commit 60ee644

File tree

2 files changed

+86
-16
lines changed

2 files changed

+86
-16
lines changed

crates/pyndakaas/python/tests/test_modelling.py

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
def test_bool_lin():
55
f = pindakaas.CNF()
66
x, y, z = f.new_vars(3)
7-
c = x + y - z + 2
8-
assert str(c) == "-x₃ + x₂ + x₁ + 2"
9-
c = sum([y, y, z], x)
10-
assert str(c) == "x₃ + x₂ + x₂ + x₁"
7+
assert str(x + 2) == "x₁ + 2", "__add__ incorrect"
8+
assert str(2 + x) == "x₁ + 2", "__radd__ incorrect"
9+
assert str(x - 2) == "x₁ + -2", "__sub__ incorrect"
10+
assert str(2 * x) == "2*x₁", "__mul__ incorrect"
11+
assert str(x * 2) == "2*x₁", "__rmul__ incorrect"
12+
assert str(x + y - z + 2) == "-x₃ + x₂ + x₁ + 2"
13+
c = sum([x, y, z])
14+
assert str(c) == "x₃ + x₂ + x₁"
1115
c *= 2
12-
assert str(c) == "2*x₃ + 2*x₂ + 2*x₂ + 2*x₁"
16+
assert str(c) == "2*x₃ + 2*x₂ + 2*x₁"
1317
c = x + y + z
1418
d = c == 2
1519
assert str(d) == "x₃ + x₂ + x₁ == 2"
@@ -18,17 +22,43 @@ def test_bool_lin():
1822
d = c >= 2
1923
assert str(d) == "x₃ + x₂ + x₁ >= 2"
2024

25+
def test_bool_lin_ops():
26+
f = pindakaas.CNF()
27+
x, y, z = f.new_vars(3)
28+
f = x + y
29+
g = x - z
30+
assert str(f + 2) == "x₂ + x₁ + 2", "__add__ incorrect"
31+
assert str(2 + f) == "x₂ + x₁ + 2", "__radd__ incorrect"
32+
assert str(f + g) == "-x₃ + x₁ + x₂ + x₁", "__add__ incorrect"
33+
assert str(f * 2) == "2*x₂ + 2*x₁", "__mul__ incorrect"
34+
assert str(2 * f) == "2*x₂ + 2*x₁", "__rmul__ incorrect"
2135

22-
def test_lit_ops():
36+
def test_formula_ops():
2337
f = pindakaas.CNF()
2438
x, y, z = f.new_vars(3)
25-
a = ~x | ~y
26-
assert str(a) == "¬x₁ ∨ ¬x₂"
27-
b = y & z
28-
assert str(b) == "x₂ ∧ x₃"
29-
c = x ^ y
30-
assert str(c) == "x₁ ⊻ x₂"
31-
d = x ^ True
32-
assert str(d) == "x₁ ⊻ true"
33-
e = x == y
34-
assert str(e) == "x₁ ≡ x₂"
39+
f = x & y
40+
g = x | z
41+
assert str(f & True) == "x₁ ∧ x₂ ∧ true", "__and__ incorrect"
42+
assert str(True & f) == "x₁ ∧ x₂ ∧ true", "__rand__ incorrect"
43+
assert str(f & g) == "x₁ ∧ x₂ ∧ (x₁ ∨ x₃)", "__and__ incorrect"
44+
assert str(f | True) == "(x₁ ∧ x₂) ∨ true", "__or__ incorrect"
45+
assert str(True | f) == "(x₁ ∧ x₂) ∨ true", "__ror__ incorrect"
46+
assert str(f | g) == "x₁ ∨ x₃ ∨ (x₁ ∧ x₂)", "__or__ incorrect"
47+
assert str(f ^ True) == "(x₁ ∧ x₂) ⊻ true", "__xor__ incorrect"
48+
assert str(True ^ f) == "(x₁ ∧ x₂) ⊻ true", "__rxor__ incorrect"
49+
assert str(f ^ g) == "(x₁ ∧ x₂) ⊻ (x₁ ∨ x₃)", "__xor__ incorrect"
50+
51+
def test_lit_ops():
52+
f = pindakaas.CNF()
53+
x, y = f.new_vars(2)
54+
assert str(x & True) == "x₁ ∧ true", "__and__ incorrect"
55+
assert str(True & x) == "x₁ ∧ true", "__rand__ incorrect"
56+
assert str(x | True) == "x₁ ∨ true", "__or__ incorrect"
57+
assert str(True | x) == "x₁ ∨ true", "__ror__ incorrect"
58+
assert str(x ^ True) == "x₁ ⊻ true", "__xor__ incorrect"
59+
assert str(True ^ x) == "x₁ ⊻ true", "__rxor__ incorrect"
60+
assert str(~x | ~y) == "¬x₁ ∨ ¬x₂"
61+
assert str(x & y) == "x₁ ∧ x₂"
62+
assert str(x ^ y) == "x₁ ⊻ x₂"
63+
assert str(x == y) == "x₁ ≡ x₂"
64+

crates/pyndakaas/src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ mod pindakaas {
224224
res
225225
}
226226

227+
fn __radd__(&self, other: BoolLinArg) -> Self {
228+
self.__add__(other)
229+
}
230+
227231
fn __eq__(&self, other: i64) -> BoolLinCon {
228232
BoolLinCon(BaseBoolLinCon::new(
229233
self.0.clone(),
@@ -274,6 +278,10 @@ mod pindakaas {
274278
res
275279
}
276280

281+
fn __rmul__(&self, other: i64) -> Self {
282+
self.__mul__(other)
283+
}
284+
277285
fn __neg__(&self) -> Self {
278286
Self(-self.0.clone())
279287
}
@@ -330,6 +338,10 @@ mod pindakaas {
330338
Self(self.0.clone() & other.as_formula())
331339
}
332340

341+
fn __rand__(&self, other: FormulaArg) -> Self {
342+
self.__and__(other)
343+
}
344+
333345
fn __eq__(&self, other: FormulaArg) -> Self {
334346
use BaseFormula::*;
335347

@@ -368,13 +380,21 @@ mod pindakaas {
368380
Formula(self.0.clone() | other.as_formula())
369381
}
370382

383+
fn __ror__(&self, other: FormulaArg) -> Self {
384+
self.__or__(other)
385+
}
386+
371387
fn __str__(&self) -> String {
372388
self.0.to_string()
373389
}
374390

375391
fn __xor__(&self, other: FormulaArg) -> Self {
376392
Formula(self.0.clone() ^ other.as_formula())
377393
}
394+
395+
fn __rxor__(&self, other: FormulaArg) -> Self {
396+
self.__xor__(other)
397+
}
378398
}
379399

380400
impl FormulaArg {
@@ -407,10 +427,18 @@ mod pindakaas {
407427
self.as_bool_lin_exp().__add__(other)
408428
}
409429

430+
fn __radd__(&self, other: BoolLinArg) -> BoolLinExp {
431+
self.__add__(other)
432+
}
433+
410434
fn __and__(&self, other: FormulaArg) -> Formula {
411435
Formula(self.as_formula()).__and__(other)
412436
}
413437

438+
fn __rand__(&self, other: FormulaArg) -> Formula {
439+
Formula(self.as_formula()).__and__(other)
440+
}
441+
414442
fn __eq__(&self, other: FormulaArg) -> Formula {
415443
Formula(self.as_formula()).__eq__(other)
416444
}
@@ -443,6 +471,10 @@ mod pindakaas {
443471
self.as_bool_lin_exp().__mul__(other)
444472
}
445473

474+
fn __rmul__(&self, other: i64) -> BoolLinExp {
475+
self.__mul__(other)
476+
}
477+
446478
fn __ne__(&self, other: FormulaArg) -> Formula {
447479
Formula(self.as_formula()).__ne__(other)
448480
}
@@ -451,6 +483,10 @@ mod pindakaas {
451483
Formula(self.as_formula()).__or__(other)
452484
}
453485

486+
fn __ror__(&self, other: FormulaArg) -> Formula {
487+
self.__or__(other)
488+
}
489+
454490
fn __str__(&self) -> String {
455491
self.0.to_string()
456492
}
@@ -463,6 +499,10 @@ mod pindakaas {
463499
Formula(self.as_formula()).__xor__(other)
464500
}
465501

502+
fn __rxor__(&self, other: FormulaArg) -> Formula {
503+
self.__xor__(other)
504+
}
505+
466506
pub fn is_negated(&self) -> bool {
467507
self.0.is_negated()
468508
}

0 commit comments

Comments
 (0)